package com.mycase.im.boot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mycase.im.boot.entity.database.ImChatGroup;
import com.mycase.im.boot.entity.database.ImChatGroupUser;
import com.mycase.im.boot.entity.database.ImGroupMessageBody;
import com.mycase.im.boot.entity.database.ImMessage;
import com.mycase.im.boot.exception.CustomException;
import com.mycase.im.boot.mapper.ChatGroupUserMapper;
import com.mycase.im.boot.mapper.GroupMessageBodyMapper;
import com.mycase.im.boot.mapper.MessageMapper;
import com.mycase.im.boot.mapper.UserMapper;
import com.mycase.im.boot.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @Author ZhuHJay
 * @Date 2021/8/21 10:07
 */
@Service
@Transactional(rollbackFor = CustomException.class)
public class MessageServiceImpl extends ServiceImpl<MessageMapper, ImMessage> implements MessageService {

    @Autowired
    private GroupMessageBodyMapper groupMessageBodyMapper;
    @Autowired
    private ChatGroupUserMapper chatGroupUserMapper;
    @Autowired
    private UserMapper userMapper;

    @Override
    public List<ImMessage> getMessageRecord(String id, String fId) {
        QueryWrapper<ImMessage> imMessageQueryWrapper = new QueryWrapper<>();
        imMessageQueryWrapper
                // 发送人 我, 接收人 好友
                .and(w -> w.eq("to_id", id).eq("from_id", fId))
                // 发送人 好友, 接收人 我
                .or(w -> w.eq("to_id", fId).eq("from_id", id))
                // 按照时间升序排序
                .orderByAsc("send_time");
        return list(imMessageQueryWrapper);
    }

    @Override
    public Integer getMessageUnReadCount(String fromId, String toId) {
        QueryWrapper<ImMessage> imMessageQueryWrapper = new QueryWrapper<>();
        imMessageQueryWrapper
                // 发送人是好友
                .eq("from_id", fromId)
                // 接收人是我
                .eq("to_id", toId)
                // 消息处于未读状态
                .eq("read_status", 0);
        return count(imMessageQueryWrapper);
    }

    @Override
    public void unReadMessageConvert(String fromId, String toId) {
        UpdateWrapper<ImMessage> imMessageUpdateWrapper = new UpdateWrapper<>();
        imMessageUpdateWrapper
                // 修改为已读
                .set("read_status", 1)
                // 好友作为发送人
                .eq("from_id", fromId)
                // 我作为接收人
                .eq("to_id", toId)
                // 消息处于未读状态
                .eq("read_status", 0);
        update(imMessageUpdateWrapper);
    }

    @Override
    public void getGroupMessageRecord(String id, ImChatGroup group) {
        final Date[] joinTime = new Date[1];
        // 获取该用户的添加群聊的时间
        group.getGroupUsers().forEach(item -> {
            if( item.getUserId().equals(id) ){
                joinTime[0] = item.getJoinTime();
            }
        });

        QueryWrapper<ImMessage> imMessageQueryWrapper = new QueryWrapper<>();
        // 只获取加入时间以后的聊天记录
        imMessageQueryWrapper
                // 消息是群聊
                .eq("type", 1)
                // 群组是对应的
                .eq("group_id", group.getId())
                // 所能获取的聊天记录是在加入群后的时间 (>=)
                .ge("send_time", joinTime[0])
                // 进行生序排列
                .orderByAsc("send_time");
        List<ImMessage> messageList = list(imMessageQueryWrapper);

        // 将获取消息体, 顺便统计未读消息数
        QueryWrapper<ImGroupMessageBody> imGroupMessageBodyQueryWrapper = new QueryWrapper<>();
        final int[] unReadCount = {0};
        // 真正存在的聊天记录(上面查出来的所有聊天记录, 可能该用户已经删除了部分, 或者全部进行了删除, 我们需要筛查)
        List<ImMessage> realRecord = new ArrayList<>();
        // 开始进行聊天记录内容体的获取以及聊天记录的筛查
        messageList.forEach(message -> {
            // 从群成员列表中获取发送该消息的成员的个人信息
            for (ImChatGroupUser imChatGroupUser : group.getGroupUsers()) {
                if( imChatGroupUser.getUserId().equals(message.getFromId()) ){
                    message.setFromImUser(imChatGroupUser.getImUser());
                    break;
                }
            }

            imGroupMessageBodyQueryWrapper
                    // 要根据该用户还有聊天记录中存储的内容体
                    .eq("user_id", id)
                    // 并且没有删除的
                    .eq("record", 1)
                    // 以及内容体
                    .eq("message_body_id", message.getToId());
            ImGroupMessageBody imGroupMessageBody = groupMessageBodyMapper.selectOne(imGroupMessageBodyQueryWrapper);
            // 每次使用完包装器, 就清除一下, 以便下一次的使用
            imGroupMessageBodyQueryWrapper.clear();
            // 如果查询到记录, 那么说明存在该聊天记录, 才进行之后的操作
            if( imGroupMessageBody != null ){
                message.setImGroupMessageBody(imGroupMessageBody);
                // 将该聊天记录存到真正的集合中
                realRecord.add(message);
                // 统计消息未读
                if( imGroupMessageBody.getReadStatus() == 0 ){
                    unReadCount[0]++;
                }
            }
        });

        // 修改消息未读
        group.setUnReadCount(unReadCount[0]);
        // 修改群聊消息记录(主要: 要的是筛查过后的聊天记录)
        group.setChatRecord(realRecord);
    }

    @Override
    public List<ImChatGroupUser> createdGroupMessage(ImMessage message) {
        // 添加一条消息, 需要一个内容体, 内容体中需要插入等同当前群聊的用数的数据量
        // 获取当前群聊的所有用户
        List<ImChatGroupUser> groupUserList = chatGroupUserMapper.selectList(
                new QueryWrapper<ImChatGroupUser>()
                        .eq("chat_group_id", message.getGroupId()));
        // 创建消息体(先创建JavaBean是为了节省空间以及 可以保存同一批次的 uuid)
        ImGroupMessageBody imGroupMessageBody = new ImGroupMessageBody();
        groupUserList.forEach(user -> {
            imGroupMessageBody.setUserId(user.getUserId());
            // 判断如果是自己, 那么消息已读
            if( user.getUserId().equals(message.getFromId()) ){
                imGroupMessageBody.setReadStatus(1);
            }else{
                imGroupMessageBody.setReadStatus(0);
            }
            if( groupMessageBodyMapper.insert(imGroupMessageBody) != 1 ){
                throw new CustomException("操作失败");
            }
        });
        // 补全 聊天记录 Bean
        // 修改接收人为 消息体
        message.setToId(imGroupMessageBody.getMessageBodyId());
        // 持久化数据
        if( !save(message) ){
            throw new CustomException("聊天记录保存失败");
        }
        return groupUserList;
    }

    @Override
    public List<ImMessage> getInviteNotifyMessage(String groupId, String fromId, int inviteCount) {
        QueryWrapper<ImMessage> imMessageQueryWrapper = new QueryWrapper<>();
        imMessageQueryWrapper
                .eq("from_id", fromId)
                .eq("group_id", groupId)
                // 群聊
                .eq("type", 1)
                // 通知类型
                .eq("notify", 1)
                // 降序, id或者时间都行
                .orderByDesc("send_time")
                // 使用插入最后的sql来limit: 从0开始, 获取inviteCount条记录
                .last("limit 0," + inviteCount);
        // 获取到的数据是倒叙的, 需要翻转过来
        List<ImMessage> list = list(imMessageQueryWrapper);
        // 将集合进行翻转
        Collections.reverse(list);
        return list;
    }

}
